19. Solution: Dependency Injection
Solution: Dependency Injection
ND079 JPND C2 L03 A19a Solution Dependency Injection V2
ExpirationChecker.java
import javax.inject.Inject;
import java.io.IOException;
import java.nio.file.Path;
import java.time.Clock;
import java.time.Duration;
import java.time.Instant;
import java.util.List;
import java.util.stream.Collectors;
public final class ExpirationChecker {
private final Clock clock;
private final MetadataFetcher metadataFetcher;
@Inject
ExpirationChecker(Clock clock, MetadataFetcher metadataFetcher) {
this.clock = clock;
this.metadataFetcher = metadataFetcher;
}
public List<Path> getExpiredFiles(List<Path> paths, Duration expiration) {
return paths.stream()
.filter((path) -> isExpired(path, expiration))
.collect(Collectors.toList());
}
private boolean isExpired(Path path, Duration expiration) {
Instant now = clock.instant();
try {
Instant modifiedTime = metadataFetcher.getLastModifiedTime(path);
return now.isAfter(modifiedTime.plus(expiration));
} catch (IOException e) {
return false;
}
}
}
ExpirationCheckerModule.java
import com.google.inject.AbstractModule;
import java.time.Clock;
public final class ExpirationCheckerModule extends AbstractModule {
@Override
protected void configure() {
bind(MetadataFetcher.class).to(MetadataFetcherImpl.class);
bind(Clock.class).toInstance(Clock.systemUTC());
}
}
ExpirationCheckerTest.java
import java.nio.file.Path;
import java.time.Duration;
import java.time.Instant;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public final class ExpirationCheckerTest {
public static void main(String[] args) {
FakeClock fakeClock = new FakeClock();
Map<Path, Instant> fakeModifiedTimes = new HashMap<>();
FakeMetadataFetcher fakeMetadataFetcher = new FakeMetadataFetcher(fakeModifiedTimes);
Injector injector = Guice.createInjector(
b -> b.bind(Clock.class).toInstance(fakeClock),
b -> b.bind(MetadataFetcher.class).toInstance(fakeMetadataFetcher));
ExpirationChecker checker = injector.getInstance(ExpirationChecker.class);
Path expired = Path.of("/test/expired");
Path notExpired = Path.of("/test/not-expired");
fakeModifiedTimes.put(expired, fakeClock.instant().minus(Duration.ofDays(31)));
fakeModifiedTimes.put(notExpired, fakeClock.instant().minus(Duration.ofDays(27)));
List<Path> expiredFiles =
checker.getExpiredFiles(List.of(expired, notExpired), Duration.ofDays(30));
assert expiredFiles.equals(List.of(expired));
}
}
Main.java
import com.google.inject.Guice;
import com.google.inject.Injector;
import java.nio.file.Path;
import java.time.Duration;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public final class Main {
public static void main(String[] args) {
Injector injector = Guice.createInjector(new ExpirationCheckerModule());
ExpirationChecker checker = injector.getInstance(ExpirationChecker.class);
List<Path> paths = Arrays.stream(args).map(Path::of).collect(Collectors.toList());
System.out.println("The following files are expired: "
+ checker.getExpiredFiles(paths, Duration.ofDays(28)));
}
}
So, Why Use Dependency Injection?
ND079 JPND C2 L03 A19b Why Use Dependency Injection